
package dieci.database.rawmaterial;

import dieci.database.PersistentObject;
import dieci.database.SessionFactoryUtil;
import dieci.hibernate.HibRawMaterialProduct;
import dieci.managers.rawmaterial.RawMaterialManager;
import dieci.managers.stockmanager.ProductManager;
import dieci.system.Product;
import dieci.system.RawMaterial;
import dieci.system.RawMaterialProduct;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;

/**
 *
 * @author DuckSys
 */
public class RawMaterialProductHibernateDAO implements RawMaterialProductDAO
{
    private static Logger logger = Logger.getLogger("RawMaterialProductHibernateDAO.log");
    private RawMaterialManager rawMaterialManager = new RawMaterialManager();
    private ProductManager productManager = new ProductManager();
    
    @Override
    public List<RawMaterialProduct> list()
    {
        List<RawMaterialProduct> rawMaterials = new ArrayList<>();

        Session session = SessionFactoryUtil.getInstance().getCurrentSession();
        try {
            session.beginTransaction();

            List<HibRawMaterialProduct> hibRawMaterialProducts = session.createCriteria(HibRawMaterialProduct.class).list();
            for (HibRawMaterialProduct dbRawMaterialProduct : hibRawMaterialProducts) {
                Product product = findProductById(dbRawMaterialProduct.getProductId());
                RawMaterial rawMaterial = findRawMaterialById(dbRawMaterialProduct.getRawMaterialId());
                RawMaterialProduct material = new RawMaterialProduct(product, rawMaterial,dbRawMaterialProduct.getAmount());
                rawMaterials.add(material);
            }

            return rawMaterials;
        }
        catch (Exception e) {

            logger.log(Level.INFO, "Error listando materia prima productos", e.getMessage());

            throw new IllegalStateException("Error al listar",e);
        }
        finally {
            if (session!=null && session.isOpen()) {

                session.close();
            }
        }

    }
    

    @Override
    public void saveOrUpdate(PersistentObject object)
    {
        Session session = null;

        RawMaterialProduct rawMaterialProduct = (RawMaterialProduct) object;
        RawMaterialProduct found = findById(rawMaterialProduct.getProduct().getProductId(),rawMaterialProduct.getRawMaterial().getRawMaterialId());
        try {
            session = SessionFactoryUtil.getInstance().getCurrentSession();
            
            session.beginTransaction();

            if (found != null) 
            {
                //UPDATE
                HibRawMaterialProduct hibRawMaterialProduct = new HibRawMaterialProduct(found);
                session.saveOrUpdate(hibRawMaterialProduct);

            }
            else 
            {
                //NEW
                HibRawMaterialProduct hibRawMaterialProduct = new HibRawMaterialProduct(rawMaterialProduct);

                // generate new id
                session.save(hibRawMaterialProduct);
                
            }

            session.getTransaction().commit();

        }
        catch (Exception e) {
            if(session!=null){
                session.getTransaction().rollback();
            } 
            throw new IllegalStateException("Error al guardar o actualizar",e);
        }
        finally {
            if (session!=null && session.isOpen()) {

                session.close();
            }
        }
    
    }

    @Override
    public void delete(PersistentObject object)
    {
        Session session = null;

        RawMaterialProduct rawMaterialProduct = (RawMaterialProduct) object;
        RawMaterialProduct found = findById(rawMaterialProduct.getProduct().getProductId(),rawMaterialProduct.getRawMaterial().getRawMaterialId());
        try {
            session = SessionFactoryUtil.getInstance().getCurrentSession();
            
            session.beginTransaction();

            if (found != null) 
            {
                //UPDATE
                HibRawMaterialProduct hibRawMaterialProduct = new HibRawMaterialProduct(found);
                session.delete(hibRawMaterialProduct);

            }
            
            session.getTransaction().commit();

        }
        catch (Exception e) {
            if(session!=null){
                session.getTransaction().rollback();
            }            
            throw new IllegalStateException("Error al eliminar",e);
        }
        finally {
            if (session!=null && session.isOpen()) {

                session.close();
            }
        }
    }

    public RawMaterialProduct findById(long prodId, int rawMatId)
    {
        RawMaterialProduct result = null;
        Session session = SessionFactoryUtil.getInstance().getCurrentSession();
        try {
            session.beginTransaction();

            HibRawMaterialProduct hibRawMaterialProduct = (HibRawMaterialProduct)session.createCriteria(HibRawMaterialProduct.class).add(Restrictions.and(Restrictions.eq("productId", prodId), Restrictions.eq("rawMaterialId", rawMatId))).uniqueResult();
            if(hibRawMaterialProduct != null)
            {
                
                result = new RawMaterialProduct(findProductById(hibRawMaterialProduct.getProductId()),findRawMaterialById(hibRawMaterialProduct.getRawMaterialId()),hibRawMaterialProduct.getAmount());
            }
            
        }
        catch (Exception e) {
            throw new IllegalStateException("Error al buscar por id",e);
        }
        finally {
            if (session!=null && session.isOpen()) {

                session.close();
            }
        }

        return result;
    }

    @Override
    public List<RawMaterialProduct> findByProduct(Product product)
    {
        List<RawMaterialProduct> result = new ArrayList<>();
        Session session = SessionFactoryUtil.getInstance().getCurrentSession();
        try {
            session.beginTransaction();

            List<HibRawMaterialProduct> hibRawMaterialProductList = session.createCriteria(HibRawMaterialProduct.class).add(Restrictions.eq("productId", product.getProductId())).list();
            for (HibRawMaterialProduct hibRawMaterialProduct : hibRawMaterialProductList)
            {
                result.add(new RawMaterialProduct(findProductById(hibRawMaterialProduct.getProductId()),
                        findRawMaterialById(hibRawMaterialProduct.getRawMaterialId()),hibRawMaterialProduct.getAmount()));
            }

        }
        catch (Exception e) {
            throw new IllegalStateException("Error al buscar por producto",e);
        }
        finally {
            if (session!=null && session.isOpen()) {

                session.close();
            }
        }

        return result;
    }

    @Override
    public List<RawMaterialProduct> findByRawMaterial(RawMaterial rawMaterial)
    {
        List<RawMaterialProduct> result = new ArrayList<>();
        Session session = SessionFactoryUtil.getInstance().getCurrentSession();
        try {
            session.beginTransaction();

            List<HibRawMaterialProduct> hibRawMaterialProductList = session.createCriteria(HibRawMaterialProduct.class).add(Restrictions.eq("rawMaterialId", rawMaterial.getRawMaterialId())).list();
            for (HibRawMaterialProduct hibRawMaterialProduct : hibRawMaterialProductList)
            {
                result.add(new RawMaterialProduct(findProductById(hibRawMaterialProduct.getProductId()),
                        findRawMaterialById(hibRawMaterialProduct.getRawMaterialId()),hibRawMaterialProduct.getAmount()));
            }

        }
        catch (Exception e) {
            throw new IllegalStateException("Error al buscar por producto",e);
        }
        finally {
            if (session!=null && session.isOpen()) {

                session.close();
            }
        }

        return result;
    }

    private Product findProductById(long productId)
    {
        return productManager.findById(productId);
    }

    private RawMaterial findRawMaterialById(int rawMaterialId)
    {
        return rawMaterialManager.findById(rawMaterialId);
    }

}
